<!DOCTYPE html>
<html>
  <!--
    Copyright 2009 Google Inc. All Rights Reserved.

    Use of this source code is governed by an Apache 2.0 License.
    See the COPYING file for details.
  -->

  <!--
  Unit tests for spilloverdetector.js.
  -->
  <head>
    <title>bidichecker - Javascript Unit Tests</title>
    <script type="text/javascript" src="../third_party/closure-library/closure/goog/base.js">
    </script>

    <!-- Include the generated deps.js which enables goog.require of
         the modules under test.
    -->
    <script type="text/javascript" src="deps.js"></script>
    <script type="text/javascript">
// This in turn pulls in the rest of the files.
goog.require('bidichecker');

goog.require('goog.testing.jsunit');
    </script>
    <script type="text/javascript" src="testutils.js"></script>

  </head>
  <body>
    <script type="text/javascript">

/**
 * Runs the spillover checker on the contents of a DOM element.
 * @param {!Element} rootElement The root element of the DOM to be checked.
 * @return {!Array.<!bidichecker.Error>} List of error messages.
 */
function runSpilloverDetector(rootElement) {
  var errorCollector =
      new bidichecker.ErrorCollector(new bidichecker.FrameStack());

  var scanner = new bidichecker.Scanner();
  // Override the buildDetectors method to build only one detector.
  scanner.buildDetectors = function(element, shouldBeRtl) {
    return [new bidichecker.SpilloverDetector(errorCollector)];
  };

  scanner.scan(rootElement);
  return errorCollector.getErrors();
}


function testSpilloverDetector_SpilloverToNumberAfterLtr() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p><span dir=\'ltr\'>Rambo<\/span>(5.67)<\/p>';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared LTR spillover to number',
                   'atText': '(5.67',
                   'precededByText': 'Rambo',
                   'severity': 2,
                   'locationDescription':
                       '<div dir=\'rtl\' id=\'test\'><p>'}];
  assertErrorFields(expected, errors);

  // The error is located in characters 0-5 of the text node reading '(5.67)'.
  var numbersNode = testDiv.firstChild.childNodes[1];
  var highlightableArea =
      new bidichecker.HighlightableText([numbersNode], 0, 5);
  assertObjectEquals(highlightableArea, errors[0].getHighlightableArea());
}


function testSpilloverDetector_SpilloverToNumberAfterLtrLowSeverity() {
  // As above, but enclosing paragraph has declared directionality, demoting the
  // error severity.
  var testDiv = goog.dom.createDom('div', {'id': 'test'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p dir=\'rtl\'><span dir=\'ltr\'>Rambo<\/span>' +
      // Hebrew text for "(5.67 Shalom)"
      '(5.67 \u05e9\u05dc\u05d5\u05dd)<\/p>';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared LTR spillover to number',
                   'atText': '(5.67',
                   'precededByText': 'Rambo',
                   'severity': 4,
                   'locationDescription':
                       '<div id=\'test\'><p dir=\'rtl\'>'}];
  assertErrorFields(expected, errors);
}


function testSpilloverDetector_SpilloverToNumberAfterRtl() {
  // Reverse the directionality from above.
  var testDiv = goog.dom.createDom('div', {'id': 'test'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p><span dir=\'rtl\'>' +
      // Hebrew text for "Shalom: {"
      '\u05e9\u05dc\u05d5\u05dd: {' +
      '<\/span>}@@ 5 Shalom<\/p>';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared RTL spillover to number',
                   'atText': '}@@ 5',
                   'precededByText': '\u05e9\u05dc\u05d5\u05dd: {',
                   'severity': 2,
                   'locationDescription':
                       '<div id=\'test\'><p>'}];
  assertErrorFields(expected, errors);
}


function testSpilloverDetector_SpilloverToNumberAfterDeclaredRtl() {
  // Don't actually need RTL text for spillover, just an RTL declaration.
  var testDiv = goog.dom.createDom('div', {'id': 'test'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p><span dir=\'rtl\'>friends<\/span>5,012.7 meters<\/p>';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared RTL spillover to number',
                   'atText': '5,012.7',
                   'precededByText': 'friends',
                   'severity': 2,
                   'locationDescription':
                       '<div id=\'test\'><p>'}];
  assertErrorFields(expected, errors);
}


function testSpilloverDetector_NoSpilloverToNumberOutOfBlock() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<div><div dir=\'ltr\'>Rambo<\/div>(5.67)<\/div>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverToNumberIntoBlock() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<span dir=\'ltr\'>Rambo<\/span><div>(5.67)<\/div>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_RlmCharacterPreventsSpilloverError() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p><span dir=\'ltr\'>Rambo<\/span>' +
      // Unicode RLM, then some numbers.
      '\u200F 5.724/12.3<\/p>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_LrmCharacterPreventsSpilloverError() {
  var testDiv = goog.dom.createDom('div', {'id': 'test'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<p><span dir=\'rtl\'>' +
      // Hebrew text for "Shalom: {"
      '\u05e9\u05dc\u05d5\u05dd: {<\/span>' +
      // Unicode RLM, then some numbers.
      '\u200E 5.234<\/p>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_SpilloverToNumberAcrossBreak() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<span dir=\'ltr\'>Rambo<\/span><br>(5.67)';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared LTR spillover to number',
                   'atText': '(5.67',
                   'precededByText': 'Rambo',
                   'severity': 2,
                   'locationDescription':
                       '<div dir=\'rtl\' id=\'test\'>'}];
  assertErrorFields(expected, errors);
}


function testSpilloverDetector_SpilloverToNumberAcrossInlineElements() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<span dir=\'ltr\'>Rambo<\/span>' +
      '<a href=\'http://www.google.com\'>++++<\/a>(5.67)';
  var errors = runSpilloverDetector(testDiv);

  var expected = [{'type': 'Declared LTR spillover to number',
                   'atText': '++++(5.67',
                   'precededByText': 'Rambo',
                   'severity': 2,
                   'locationDescription':
                       '<div dir=\'rtl\' id=\'test\'>'}];
  assertErrorFields(expected, errors);

  // The error crosses two text nodes this time.
  var plussesNode = testDiv.childNodes[1].firstChild;
  var numbersNode = testDiv.childNodes[2];
  var highlightableArea = new bidichecker.HighlightableText(
      [plussesNode, numbersNode], 0, 5);
  assertObjectEquals(highlightableArea, errors[0].getHighlightableArea());
}


function testSpilloverDetector_SpilloverToNumberAcrossEmbeddedBlockFails() {
  // Technically, this is a spillover situation (at least in Firefox), but
  // the algorithm isn't currently sophisticated enough to catch it.
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '<span dir=\'ltr\'>Rambo<\/span><div><\/div>(5.67)';
  var errors = runSpilloverDetector(testDiv);

  // Expect no errors, even though arguably there should be one.
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverErrorIfNewExplicitDir() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML =
      '<span dir=\'ltr\'>Shalom<\/span> - <span dir=\'rtl\'>50<\/span>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverErrorIfSpaceBetweenCloseSpanTags() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML =
      '<span dir=\'rtl\'><span dir=\'ltr\'>Double wrap<\/span> <\/span> - 50';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverErrorAcrossEmptySpan() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML =
      '<span dir=\'ltr\'>Rambo<\/span><span dir=\'rtl\'><\/span> - 50';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverIfNumberInsideOppositeDirElement() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML =
      // Hebrew text for "Shalom"
      '<p><span dir=\'ltr\'>Rambo 4<\/span>\u05e9\u05dc\u05d5\u05dd<\/p>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}


function testSpilloverDetector_NoSpilloverIfNumberPrecedesOppositeDirElement() {
  var testDiv = goog.dom.createDom('div', {'id': 'test', 'dir': 'rtl'});
  goog.dom.appendChild(document.body, testDiv);
  testDiv.innerHTML = '5 <span dir=\'ltr\'>Shalom<\/span>';
  var errors = runSpilloverDetector(testDiv);
  assertErrorFields([], errors);
}

    </script>

  </body>
</html>
